package com.wunong.smart.collection.starter.repository;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.Preconditions;
import com.wunong.smart.collection.client.query.CollectionQueryDTO;
import com.wunong.smart.collection.domain.model.CollectionDomain;
import com.wunong.smart.collection.repository.CollectionRepository;
import com.wunong.smart.collection.starter.infrastructure.converter.CollectionConverter;
import com.wunong.smart.collection.starter.infrastructure.mapper.CollectionMapper;
import com.wunong.smart.collection.starter.infrastructure.po.CollectionPO;
import com.wunong.smart.domain.platform.common.BizSource;
import com.wunong.smart.domain.platform.entify.User;
import com.wunong.smart.domain.platform.utils.ArrayUtils;
import com.wunong.smart.domain.platform.utils.TimeUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static com.wunong.smart.collection.starter.infrastructure.converter.CollectionConverter.toDomain;

/**
 * @author create by zealot.zt
 */
public class CollectionRepositoryImpl implements CollectionRepository {

    @Resource
    private CollectionMapper collectionMapper;

    @Override
    public Long save(CollectionDomain domain) {
        LocalDateTime now = TimeUtils.nowWithoutMs();
        domain.setGmtCreate(now);
        domain.setGmtModified(now);
        CollectionPO po = CollectionConverter.toPo(domain);

        collectionMapper.insert(po);
        domain.setId(po.getId());
        return po.getId();
    }

    @Override
    public void update(CollectionDomain domain) {
        Wrapper<CollectionPO> wrapper = Wrappers.lambdaQuery(CollectionPO.class)
                .eq(CollectionPO::getId, domain.getId())
                .eq(CollectionPO::getUserId, domain.getUserId());

        domain.setGmtModified(TimeUtils.nowWithoutMs());
        CollectionPO po = CollectionConverter.toPo(domain);

        Preconditions.checkArgument(collectionMapper.update(po, wrapper) > 0, "更新收藏失败");
    }

    @Override
    public CollectionDomain getById(Long id) {
        return toDomain(collectionMapper.selectById(id));
    }

    @Override
    public CollectionDomain getById(Long userId, Long id) {
        Wrapper<CollectionPO> wrapper = Wrappers.lambdaQuery(CollectionPO.class)
                .eq(CollectionPO::getId, id)
                .eq(CollectionPO::getUserId, userId);

        return toDomain(collectionMapper.selectOne(wrapper));
    }

    @Override
    public List<CollectionDomain> queryByBiz(BizSource source) {
        Wrapper<CollectionPO> wrapper = Wrappers.lambdaQuery(CollectionPO.class)
                .eq(CollectionPO::getBizId, source.getBizId())
                .eq(CollectionPO::getBizType, source.getBizType())
                .orderByDesc(CollectionPO::getGmtCreate);

        return toDomain(collectionMapper.selectList(wrapper));
    }

    @Override
    public CollectionDomain getByUserIdAndBiz(Long userId, BizSource source) {
        Wrapper<CollectionPO> wrapper = Wrappers.lambdaQuery(CollectionPO.class)
                .eq(CollectionPO::getUserId, userId)
                .eq(CollectionPO::getBizId, source.getBizId())
                .eq(CollectionPO::getBizType, source.getBizType())
                .orderByDesc(CollectionPO::getGmtCreate);

        return toDomain(collectionMapper.selectOne(wrapper));
    }

    @Override
    public List<CollectionDomain> query(CollectionQueryDTO queryDTO) {
        LambdaQueryWrapper<CollectionPO> wrapper = Wrappers.lambdaQuery(CollectionPO.class)
                .orderByDesc(CollectionPO::getGmtCreate);

        if (queryDTO.getId() != null) {
            wrapper.eq(CollectionPO::getId, queryDTO.getId());
        }

        User user = queryDTO.getUser();
        if (Objects.nonNull(user)) {
            if (user.getId() != null) {
                wrapper.eq(CollectionPO::getUserId, user.getIdLong());
            }
            if (user.getRole() != null) {
                wrapper.eq(CollectionPO::getUserRole, user.getRole());
            }
        }

        BizSource source = queryDTO.getSource();
        if (Objects.nonNull(source)) {
            if (StringUtils.isNotBlank(source.getBizId())) {
                wrapper.eq(CollectionPO::getBizId, source.getBizId());
            }
            if (user.getRole() != null) {
                wrapper.eq(CollectionPO::getUserRole, user.getRole());
            }
        }

        if (StringUtils.isNotBlank(queryDTO.getCollectType())) {
            wrapper.eq(CollectionPO::getCollectType, queryDTO.getCollectType());
        }

        if (ArrayUtils.isNotEmpty(queryDTO.getStatuses())) {
            wrapper.in(CollectionPO::getStatus, queryDTO.getStatuses());
        }

        return toDomain(collectionMapper.selectList(wrapper));
    }

}
